#include "common.h"
#include <cstdint>
#include <string>
#include <vector>
#include <ostream>
#include <sstream>
#include <fstream>
#include <thread>
#include <chrono>
#include <ctime>
#include <random>
#include <iomanip>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <limits.h>
#include <linux/limits.h>
#endif
#include <sys/time.h>



/******************************************************************
 * 功能：判断两个浮点数是否相等
 * 输入参数：
 *      dVal1：比较值1
 *      dVal2：比较值2
 * 返回值：
 *      bool：比较结果，true - 相等，false - 不相等
 * ****************************************************************/
bool isEqual(double dVal1, double dVal2)
{
    return (fabs(dVal1 - dVal2) < 1e-5) ? true : false;
}

/******************************************************************
 * 功能：判断系统是否小端（Intel）序，注网络序和Motorala序为大端序
 * 大端序：像我们写数字一样，最重要的部分（高位字节）放在前面的地址（低地址）
 * 小端序：像我们倒着念一样，最不重要的部分（低位字节）放在前面的地址（低地址）
 * 返回值：
 *      bool：判断结果，true - 小端序，false - 大端序
 * ****************************************************************/
/******************************************************************
 * 功能：判断系统是否大端序（网络序）
 * 注：网络序和Motorala序为大端序，小端为Intel序
 * 大端序：像我们写数字一样，最重要的部分（高位字节）放在前面的地址（低地址）
 * 小端序：像我们倒着念一样，最不重要的部分（低位字节）放在前面的地址（低地址）
 * 返回值：
 *      bool：判断结果，true - 大端序，false - 小端序
 * ****************************************************************/
bool isLocalBigEndian()
{
    int iVal = 0x01;
    char *pVal = reinterpret_cast<char *>(&iVal);
    return (*pVal == 0) ? true : false;
}

/******************************************************************
 * 功能：获取UTC格式化当前系统时间
 * 返回值：
 *      std::string：UTC格式化时间，形如：yyyy-MM-ddTHH:mm:ssZ
 * ****************************************************************/
std::string getUtcFormatCurSystemTimeISO8601()
{
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();
    // 转换为时间戳
    auto time_t_now = std::chrono::system_clock::to_time_t(now);

    // 使用线程安全的 gmtime_r
    std::tm utc_tm;
    gmtime_r(&time_t_now, &utc_tm);

    // 创建一个 stringstream 用于格式化
    std::ostringstream oss;
    // 格式化为 ISO 8601 格式
    oss << std::put_time(&utc_tm, "%Y-%m-%dT%H:%M:%SZ");

    return oss.str();
}

/******************************************************************
 * 功能：获取格式化当前系统时间
 * 返回值：
 *      std::string：格式化时间，形如：yyyy-MM-dd HH:mm:ss.zzz
 * ****************************************************************/
std::string getFormatCurSystemTime()
{
    time_t tloc;
    struct tm tm;
    struct timeval tv;

    time(&tloc);
    localtime_r(&tloc, &tm);
    gettimeofday(&tv, nullptr);

    char szTimeInfo[64] = {0};

#if 1
    char szTemp[32] = {0};
    strftime(szTemp, sizeof(szTemp), "%Y-%m-%d %H:%M:%S", &tm);
    snprintf(szTimeInfo, sizeof(szTimeInfo), "%s.%03ld", szTemp, tv.tv_usec / 1000);
#else
    snprintf(szTimeInfo, sizeof(szTimeInfo), "%04d-%02d-%02d %02d:%02d:%02d.%03ld"
             , tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday
             , tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec / 1000);
#endif

    return std::string(szTimeInfo);
}

/******************************************************************
 * 功能：获取UUID
 * 返回值：
 *      std::string：uuid_v4
 * ****************************************************************/
std::string getUUID_V4()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 15);
    std::uniform_int_distribution<> dis2(8, 11);

    std::stringstream ss;
    ss << std::hex;
    for (int i = 0; i < 8; ++i) {
        ss << dis(gen);
    }
    ss << "-";
    for (int i = 0; i < 4; ++i) {
        ss << dis(gen);
    }
    ss << "-4";  // UUID v4 固定第 13 位为 '4'
    for (int i = 0; i < 3; ++i) {
        ss << dis(gen);
    }
    ss << "-";
    ss << dis2(gen);  // UUID v4 固定第 17 位为 '8', '9', 'a', or 'b'
    for (int i = 0; i < 3; ++i) {
        ss << dis(gen);
    }
    ss << "-";
    for (int i = 0; i < 12; ++i) {
        ss << dis(gen);
    }

    return ss.str();
}

/******************************************************************
 * 功能：获取当前系统毫秒值的时间戳
 * 返回值：
 *      uint64_t：当前系统毫秒值的时间戳
 * ****************************************************************/
uint64_t getCurSystemMsTime()
{
    return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>
                                 (std::chrono::system_clock::now().time_since_epoch()).count()); // 毫秒
}

/******************************************************************
 * 功能：获取当前系统秒值的时间戳
 * 返回值：
 *      uint64_t：当前系统秒值的时间戳
 * ****************************************************************/
uint64_t getCurSystemSecTime()
{
    return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::seconds>
                                 (std::chrono::system_clock::now().time_since_epoch()).count()); // 秒
}

/***************************************************************
 * 功能：获取当前进程的PID
 * 返回值：
 *      int：当前进程的PID
 * *************************************************************/
int getCurProcessPID()
{
    return static_cast<int>(getpid());
}

/***************************************************************
 * 功能：获取当前线程的id
 * 返回值：
 *      uint64_t：当前线程的id
 * *************************************************************/
uint64_t getCurrentThreadID()
{
    std::ostringstream oss;
    oss << std::this_thread::get_id();
    std::string stId = oss.str();
    return std::stoull(stId);
}

/***************************************************************
 * 功能：获取当前程序运行进程名称
 * 返回值：
 *      std::string：当前程序运行进程名称
 * *************************************************************/
std::string getProcessName()
{
    // C++17中实现如下
    //#include <filesystem>
    //std::filesystem::path exePath = std::filesystem::canonical("/proc/self/exe"); // Linux
    //std::filesystem::path exePath = std::filesystem::canonical(GetModuleFileName(NULL)); // Windows（需包含windows.h）
    //strName = exePath.filename().string();

    std::string strName = "";

#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)
    char processName[MAX_PATH] = {0};
    DWORD length = GetModuleFileName(NULL, processName, MAX_PATH);
    if (length > 0 && length < MAX_PATH) {
        // processName为可执行文件全路径
        // 提取文件名（非完整路径）
        char* fileName = strrchr(processName, '\\');
        if (fileName) {
            strName = std::string(fileName + 1);
        }
    }
#else
    std::ifstream commFile("/proc/self/comm");
    if (commFile.is_open()) {
        std::getline(commFile, strName);
        commFile.close();
    }
#endif

    return strName;
}

/***************************************************************
 * 功能：获取当前程序运行路径
 * 返回值：
 *      std::string：当前程序运行路径
 * *************************************************************/
std::string getCurrentRunPath()
{
    // C++17中实现如下
    //#include <filesystem>
    //std::filesystem::path currentPath = std::filesystem::current_path();
    //std::string strPath = currentPath.string();
    std::string strPath = "";

#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)
#if 0
    char buffer[MAX_PATH] = {0}; // MAX_PATH为系统定义的最大路径长度
    DWORD length = GetCurrentDirectory(MAX_PATH, buffer);
    if (length > 0 && length < MAX_PATH) {
        strPath = std::string(buffer);
    }
#else
    char processName[MAX_PATH] = {0};
    DWORD length = GetModuleFileName(NULL, processName, MAX_PATH);
    if (length > 0 && length < MAX_PATH) {
        strPath = std::string(processName);
    }
#endif
#else
    char* cwd = getcwd(nullptr, 0); // 自动分配缓冲区
    if (cwd) {
        strPath = std::string(cwd) + "/" + getProcessName();
        free(cwd); // 需手动释放内存
    }
#endif

    return strPath;
}

/***************************************************************
 * 功能：获取系统主机名
 * 返回值：
 *      std::string：主机名
 * *************************************************************/
std::string getHostName()
{
    std::string strHostName = "";
#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)
    //char hostname[256] = {0};
    char hostname[MAX_COMPUTERNAME_LENGTH + 1] = {0};
    DWORD size = sizeof(hostname);
    if (GetComputerName(hostname, &size)) {
        strHostName = std::string(hostname);
    }
#else
    char hostname[128] = {0};
    //char hostname[HOST_NAME_MAX] = {0};
    if (0 == gethostname(hostname, sizeof(hostname))) {
        strHostName = std::string(hostname);
    }
#endif

    return strHostName;
}

/******************************************************************
 * 功能：获取int类型的随机化数据
 * 输入参数：
 *      iMin：下限
 *      iMax：上限
 * 返回值：
 *      int：随机值
 * ****************************************************************/
int getIntRandomNum(int iMin, int iMax)
{
    // 定义随机数生成器
    std::random_device rd;  // 随机数种子
    std::mt19937 gen(rd()); // 使用Mersenne Twister算法
    std::uniform_int_distribution<> dis(iMin, iMax); // int类型定义范围[iMin, iMax]

    // 生成随机整数
    int iRandomNumber = dis(gen);
    return iRandomNumber;
}

/******************************************************************
 * 功能：获取double类型的随机化数据
 * 输入参数：
 *      dMin：下限
 *      dMax：上限
 * 返回值：
 *      double：随机值
 * ****************************************************************/
double getDoubleRandomNum(double dMin, double dMax)
{
#ifdef USER_DEFINE
    // 用户自定义情况
    static unsigned long sulSeed = std::chrono::steady_clock::now().time_since_epoch().count();
    sulSeed = (1664525UL * sulSeed + 1013904223UL) % 4294967296UL;
    double dSeed = static_cast<double>(sulSeed) / 4294967296.0;
    double dRandomNumber = dMin + (dMax - dMin) * dSeed;
    return dRandomNumber;
#else
    //srand((unsigned int)time(NULL));
    //double dRandomNumber = dMin + (dMax - dMin) * rand() / RAND_MAX;
    //return dRandomNumber;
    
    // 定义随机数生成器
    std::random_device rd;  // 随机数种子
    std::mt19937 gen(rd()); // 使用Mersenne Twister算法
    std::uniform_real_distribution<> dis(dMin, dMax); // double类型定义范围[dMin, dMax]

    // 生成随机整数
    double dRandomNumber = dis(gen);
    return dRandomNumber;
#endif // USER_DEFINE
}

/***************************************************************
 * 功能：按16进制打印出字符串信息
 * 输入参数：
 *      strData：待打印的数据信息
 * *************************************************************/
void printStringHexInfo(const std::string &strData)
{
    printf("========================================================\r\n");
    for (size_t i = 0, size = strData.size(); i < size; ++i) {
        printf("%02x ", static_cast<uint8_t>(strData[i]));
    }
    printf("\r\n========================================================\r\n");
    return;
}
